﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Windows.Forms;
using System.Xml.Serialization;
using Fsxm.LispEdit;
using Fsxm;
using WeifenLuo.WinFormsUI.Docking;


namespace PluginMain
{
    public partial class ProjectManage : DockContent
    {
        //编辑器的文件地址
        private string _editFilePath;
        //模版文件地址
        private string _projectManageFilePath;
        //输入文件地址的对话框
        private InputDirsName _inputForm;
        //当前选择项目的地址
        private string _curProjectPath;
        //当前的项目
        private Project _curProject;
        //鼠标位置
        private Point _mousePoint;
        //
        private
        MainForm _editApp = Plugin.EditApp;
        //当前点击节点
        TreeNode _curNode;
        //当前文件夹
        string _curDirPath;
        //
        LispTextBox _edit = Plugin.ActivateEdit;

        TreeNodeCollection _curTreeNodeS;
        List<string> _oldFileS;



        public ProjectManage()
        {
            InitializeComponent();
            _editFilePath = Application.StartupPath;
            _projectManageFilePath = _editFilePath + "\\PrjManage\\";
            _oldFileS = (List<string>)Fsxm.LispEdit.Project.Files.ToList();
            if (!File.Exists(_projectManageFilePath))
            {
                Directory.CreateDirectory(_projectManageFilePath);
            }
            UpdateTree();
        }

        private void CloseForm_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        //在树的地方按下鼠标
        private void treeView1_MouseDown(object sender, MouseEventArgs e)
        {
            _mousePoint = new Point(e.X, e.Y);
            _curNode = treeView1.GetNodeAt(_mousePoint);
            if (e.Button == MouseButtons.Right)
            {

                if (_curNode != null)
                {
                    _curTreeNodeS = _curNode.Nodes;
                    switch (_curNode.ImageIndex)
                    {
                        case 0:
                            _curNode.ContextMenuStrip = contextMenuStrip1;
                            _curDirPath = _projectManageFilePath + _curNode.FullPath + "\\";
                            break;
                        case 1:
                            //项目 单选
                            _curNode.ContextMenuStrip = contextMenuStrip_Project;
                            _curProjectPath = _projectManageFilePath + _curNode.FullPath;
                            _curProject = new Project(_curProjectPath);
                            break;
                        default:
                            _curNode.ContextMenuStrip = contextMenuStrip_File;
                            break;
                    }
                }
                else
                {
                    _curTreeNodeS = treeView1.Nodes;
                    _curDirPath = _projectManageFilePath;
                    contextMenuStrip1.Show(treeView1, _mousePoint);
                }
            }
        }
        #region 右键菜单事件
        private void 管理目录QToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Process.Start(_projectManageFilePath);

        }

        private void 新建文件夹WToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                _inputForm.Close();
            }
            catch (Exception)
            {
            }
            _inputForm = new InputDirsName(_curDirPath, _curTreeNodeS, 0);
            _inputForm.Show();
            _inputForm.Location = Control.MousePosition;
        }

        private void 新建工程AToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                _inputForm.Close();
            }
            catch (Exception)
            {
            }

            _inputForm = new InputDirsName(_curDirPath, _curTreeNodeS, 1);
            _inputForm.Show();
            _inputForm.Location = Control.MousePosition;
            TreeNodeCollection tN = treeView1.Nodes;

        }

        private void 刷新EToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UpdateTree();
        }
        #endregion
        //树的刷新操作
        public static void TreeAdd(TreeNodeCollection tNode, string path)
        {
            string[] fils = Directory.GetFiles(path, "*.prj");
            TreeNode t;

            string[] dirs = Directory.GetDirectories(path);
            foreach (string p in dirs)
            {
                DirectoryInfo dir = new DirectoryInfo(p);
                t = tNode.Add(dir.Name, dir.Name, 0);
                t.SelectedImageIndex = 0;
                t.ImageIndex = 0;
                TreeAdd(t.Nodes, p);
            }
            foreach (string p in fils)
            {

                t = tNode.Add(Path.GetFileName(p), Path.GetFileName(p), 1);
                t.SelectedImageIndex = 1;
                t.ImageIndex = 1;
                //遍历prj里面的文件.
                Project temP = new Project(p);
                foreach (var x in temP.FileS)
                {
                    AddFileToNode(x.Key, x.Value, t);
                }
            }

        }

        private static void AddFileToNode(string fileName, string node, TreeNode tN)
        {
            TreeNode tNew = tN.Nodes.Add(node, Path.GetFileName(fileName));
            tNew.Tag = fileName;
            string s = Path.GetExtension(fileName);
            switch (s.ToLower())
            {
                case ".txt":
                    tNew.SelectedImageIndex = 4;
                    tNew.ImageIndex = 4;
                    break;
                case ".lsp":
                    tNew.SelectedImageIndex = 3;
                    tNew.ImageIndex = 3;
                    break;
                case ".dcl":
                    tNew.SelectedImageIndex = 2;
                    tNew.ImageIndex = 2;
                    break;

                default:
                    break;
            }
        }
        //更新节点树
        void UpdateTree()
        {
            treeView1.Nodes.Clear();
            treeView1.BeginUpdate();
            TreeAdd(treeView1.Nodes, _projectManageFilePath);
            treeView1.EndUpdate();
        }

        private void 添加文件ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string oldPathTxtPath = _editFilePath + "\\OldGetPath.txt";
            if (_curNode == null)
            {
                return;
            }
            OpenFileDialog openFileDialog1 = new OpenFileDialog();
            openFileDialog1.Multiselect = true;
            openFileDialog1.Filter = "Lsp,Dcl,Txt (*.lsp,*.txt,*.dcl,*.fas)|*.lsp;*.txt;*.dcl;*.fas";
            if (File.Exists(oldPathTxtPath))
            {
                openFileDialog1.InitialDirectory = File.ReadAllLines(oldPathTxtPath)[0];
            }
            else
            {
                openFileDialog1.InitialDirectory = "c:\\";
            }
            openFileDialog1.FilterIndex = 2;
            openFileDialog1.RestoreDirectory = true;

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    File.WriteAllText(oldPathTxtPath, Path.GetDirectoryName(openFileDialog1.FileNames[0]));
                    foreach (string x in openFileDialog1.FileNames)
                    {
                        _curProject.AddFile(x, "");
                    }
                    _curProject.Save();
                    _curNode.Nodes.Clear();
                    foreach (var x in _curProject.FileS)
                    {
                        AddFileToNode(x.Key, x.Value, _curNode);
                    }
                    if (_curNode.IsExpanded)
                    {
                        _curNode.Expand();
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
                }
            }
        }

        private void treeView1_KeyPress(object sender, KeyPressEventArgs e)
        {
            Debug.Print("Test");
        }

        private void treeView1_KeyUp(object sender, KeyEventArgs e)
        {

        }

        private void treeView1_KeyDown(object sender, KeyEventArgs e)
        {
            //Del
            _curNode = treeView1.SelectedNode;
            Debug.Print(e.KeyValue.ToString());
            try
            {
                if (e.KeyValue == 46 && _curNode != null)
                {
                    DelNode(_curNode);
                    _curNode.Remove();
                }
                //上移动
                else if (e.KeyValue == 38 && _curNode != null && _curNode.ImageIndex == 3)
                {
                    if (_curNode.Index > 0)
                    {
                        TreeNode t1 = _curNode.Parent.Nodes[_curNode.Index];
                        TreeNode t2 = _curNode.Parent.Nodes[_curNode.Index-1];
                        TreeNode t3 = new TreeNode();
                        //t3.FullPath = t1.FullPath;
                        t3.Text = t1.Text;
                        t3.Tag = t1.Tag;
                        //
                        t1.Tag = t2.Tag;
                        //t1.FullPath = t2.FullPath;
                        t1.Text = t2.Text;
                        //
                        t2.Text = t3.Text;
                        t2.Tag = t3.Tag;
                        //t2.FullPath = t3.FullPath;

                        _curProject.FileIndexUp(_curNode.Index);
                        _curProject.Save();
                        //_curNode.FullPath=
                    }
                }
                //下移动
                else if (e.KeyValue == 40 && _curNode != null && _curNode.ImageIndex == 3)
                {
                    if (_curNode.Index < _curNode.Parent.Nodes.Count)
                    {
                        TreeNode t1 = _curNode.Parent.Nodes[_curNode.Index];
                        TreeNode t2 = _curNode.Parent.Nodes[_curNode.Index +1];
                        TreeNode t3 = new TreeNode();
                        //t3.FullPath = t1.FullPath;
                        t3.Text = t1.Text;
                        t3.Tag = t1.Tag;
                        //
                        t1.Tag = t2.Tag;
                        //t1.FullPath = t2.FullPath;
                        t1.Text = t2.Text;
                        //
                        t2.Text = t3.Text;
                        t2.Tag = t3.Tag;
                        //t2.FullPath = t3.FullPath;

                        _curProject.FileIndexDwon(_curNode.Index);
                        //_curNode.FullPath=
                        _curProject.Save();
                    }
                }
            }
            catch (Exception)
            {
                MessageBox.Show("删除失败,可能是文件被打开了!");
            }
        }

        private void DelNode(TreeNode node)
        {
            DialogResult ResYesOrNo = MessageBox.Show("是否真的要删除?", "警告!", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (ResYesOrNo == DialogResult.Yes)
            {
                if (new[] { 2, 3, 4 }.Contains(node.ImageIndex))
                {
                    _curProject = new Project(_projectManageFilePath + node.Parent.FullPath);
                    _curProject.RemoveFile((string)node.Tag);
                    _curProject.Save();
                }
                else if (node.ImageIndex == 1)
                {
                    string projectPath = _projectManageFilePath + node.FullPath;
                    File.Delete(projectPath);
                }
                else if (node.ImageIndex == 0)
                {
                    string projectPath = _projectManageFilePath + node.FullPath;
                    Directory.Delete(projectPath);
                }
                node.Remove();
            }
        }

        private void treeView1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (_curNode == null)
            {
                return;
            }
            //Lisp
            if (_curNode.ImageIndex == 3)
            {
                string s = (string)_curNode.Tag;
                _editApp.OpenFile(s);
            }
            else if (_curNode.ImageIndex == 2 || _curNode.ImageIndex == 4)
            {
                string s = (string)_curNode.Tag;
                Process.Start(s);
            }
        }

        private void treeView1_MouseClick(object sender, MouseEventArgs e)
        {
            _mousePoint = new Point(e.X, e.Y);
            _curNode = treeView1.GetNodeAt(_mousePoint);
            if (_curNode == null)
            {
                return;
            }
            UniFils();
            switch (_curNode.ImageIndex)
            {
                case 1:
                    _curProject = new Project(_projectManageFilePath + _curNode.FullPath);
                    break;
                case 2:
                    _curProject = new Project(_projectManageFilePath + _curNode.Parent.FullPath);
                    break;
                case 3:
                    _curProject = new Project(_projectManageFilePath + _curNode.Parent.FullPath);
                    break;
                default:
                    break;
            }
            if (_curProject==null)
            {
                return;
            }
            foreach (var x in _curProject.FileS)
            {
                if (Path.GetExtension(x.Key) == ".lsp")
                {
                    if (File.Exists(x.Key))
                    {
                        Fsxm.LispEdit.Project.AddFile(x.Key);
                    }
                    else
                    {
                        MessageBox.Show("文件已经不存在:" + x.Key);
                    }
                }
            }
        }

        private void UniFils()
        {
            List<string> filsS = Fsxm.LispEdit.Project.Files.Except(_oldFileS).ToList();
            foreach (string x in filsS)
            {
                Fsxm.LispEdit.Project.RemoveFile(x);
            }
            PrintMsg("卸载函数!");
        }

        private void 加载全部项目文件ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UniFils();
            foreach (var x in _curProject.FileS)
            {
                if (Path.GetExtension(x.Key) == ".lsp")
                {
                    if (File.Exists(x.Key))
                    {
                        Fsxm.LispEdit.Project.AddFile(x.Key);
                    }
                    else
                    {
                        MessageBox.Show("文件已经不存在:" + x.Key);
                    }
                }
            }
            PrintMsg("已经卸载之前加载的函数,加载当前项目函数!");
        }

        private void 删除DToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DelNode(_curNode);
        }

        private void 删除DToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            DelNode(_curNode);
        }

        private void 一键编译XToolStripMenuItem_Click(object sender, EventArgs e)
        {
            _curProject.CreatePrvFile();
        }

        private void 打开文件所在目录FToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string path = (string)_curNode.Tag;
            Process.Start(Path.GetDirectoryName(path));
        }

        private void 打开OToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string path = (string)_curNode.Tag;
            _editApp.OpenFile(path);
        }

        private void ProjectManage_FormClosed(object sender, FormClosedEventArgs e)
        {

        }

        //打印信息
        private void PrintMsg(string msg)
        {
        }

        private void 加载项目Lsp到cadToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string s = "(progn";
            foreach (var x in _curProject.FileS)
            {
                //Plugin.LoadCode("(vl-load-all \"" +x.Key.Replace("\\","\\\\") + "\")");
                s += "(vl-load-all \"" + x.Key.Replace("\\", "\\\\") + "\")";
            }
            s += "(princ \"\n成功加载" + _curProject.FileS.Count.ToString() + "个文件.\"";
            s += ")";
            Plugin.LoadCode(s);
            PrintMsg("成功加载项目文件到CAD!");
        }

        private void 保存当前打开文件ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string[] lispFils = new string[Plugin.DocumentManager.Count()];
            for (int i = 0; i < Plugin.DocumentManager.Count(); i++)
            {
                lispFils[i] = Plugin.DocumentManager.ElementAt(i).FileName;
            }
            File.WriteAllLines(_editFilePath + "\\OldFileS.txt", lispFils);
        }

        private void 恢复打开的文件ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (var item in File.ReadAllLines(_editFilePath + "\\OldFileS.txt"))
            {
                Plugin.EditApp.OpenFile(item);
            }
        }

        private void 移除DToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //_curNode
            string path = _curNode.Tag as string;
            _curProject = new Project(_projectManageFilePath + (string)_curNode.Parent.FullPath);
            _curProject.RemoveFile(path);
            _curProject.Save();
            _curNode.Remove();
        }

        private void 添加当前文件到项目SToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string filePath = _editApp.ActivateDoc.FileName;

            if (!_curProject.FileS.ContainsKey(filePath))
            {
                _curProject.AddFile(filePath, "");
                _curProject.Save();
                AddFileToNode(filePath, "", _curNode);
            }
            else
            {
                MessageBox.Show("已经存在该文件了!");
            }

        }

        private void 打开所有文件ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (var x in _curProject.FileS)
            {
                Process.Start(x.Key);
            }
        }
    }
    //项目文件封装类
    public class Project
    {
        //项目名称
        public string sProjectName;
        //保存地址
        public string _saveFilePath;
        //文件字典表.key为文件名,val为备注
        public SerializableDictionary<string, string> FileS = new SerializableDictionary<string, string>();
        //编译选项 是否Acticex支持
        public bool _bActicex;
        //是否独立的名称空间
        public bool _bNameSpaceIsSeparate;
        public string _vlxName;
        public string _prvPath;
        //构造函数
        public Project(string projectFilePath)
        {
            this.sProjectName = Path.GetFileNameWithoutExtension(projectFilePath);
            this._saveFilePath = projectFilePath;
            if (File.Exists(projectFilePath))
            {
                XmlSerializer xmlSer = new XmlSerializer(typeof(Project));
                FileStream f2 = new FileStream(projectFilePath, FileMode.Open);
                this.FileS = ((Project)xmlSer.Deserialize(f2)).FileS;
                f2.Close();
            }
        }
        //无参数构造
        public Project() { }
        //增加文件. 文件地址 备注
        public void AddFile(string path, string node)
        {
            if (FileS.ContainsKey(path))
            {
                return;
            }
            //FileS.Contains(path)
            FileS.Add(path, node);
        }
        //自身序列化 Dir 保存的文件地址
        public void SaveToXml(string Dir)
        {
            XmlSerializer xmlSer = new XmlSerializer(typeof(Project));
            FileStream f = new FileStream(_saveFilePath, FileMode.Create);
            xmlSer.Serialize(f, this);
            f.Close();
        }
        public void Save()
        {
            SaveToXml(_saveFilePath);
        }
        //索引位置上升
        public void FileIndexUp(int index)
        {
            if (index == 0 || index > FileS.Count)
            {
                return;
            }
            KeyValuePair<string, string>[] lst = FileS.ToArray();
            FileS.Clear();
            for (int i = 0; i < index - 1; i++)
            {
                FileS.Add(lst[i].Key, lst[i].Value);
            }
            FileS.Add(lst[index].Key, lst[index].Value);
            FileS.Add(lst[index - 1].Key, lst[index - 1].Value);
            for (int i = index + 1; i < lst.Length; i++)
            {
                FileS.Add(lst[i].Key, lst[i].Value);
            }
        }
        //索引位置下降
        internal void FileIndexDwon(int index)
        {
            if (index >= FileS.Count-1)
            {
                return;
            }
            KeyValuePair<string, string>[] lst = FileS.ToArray();
            FileS.Clear();
            for (int i = 0; i < index; i++)
            {
                FileS.Add(lst[i].Key, lst[i].Value);
            }
            FileS.Add(lst[index + 1].Key, lst[index + 1].Value);
            FileS.Add(lst[index].Key, lst[index].Value);
            for (int i = index + 2; i < lst.Length; i++)
            {
                FileS.Add(lst[i].Key, lst[i].Value);
            }
        }
        //删除文件安
        public void RemoveFile(String File)
        {
            try
            {
                FileS.Remove(File);
            }
            catch (Exception)
            {
                MessageBox.Show("从字典里面删除指定的文件失败.");
            }
        }

        public void CreatePrvFile()
        {
            if (FileS.Count == 0)
            {
                MessageBox.Show("没有文件可以编译");
                return;
            }
            if (_prvPath == null)
            {
                string path = FileS.First().Key;
                string datastr = DateTime.Now.ToString();
                datastr = datastr.Replace("/", "-");
                datastr = datastr.Replace(":", "-");
                _prvPath = Path.GetDirectoryName(path) + "\\" + datastr + "\\" + sProjectName + ".prv";
            }
            if (_vlxName == null)
            {
                _vlxName = sProjectName;
            }
            string s = @";熊掌Lisp小助手生成文件.访问官网:www.youyicad.com
;插件定制有仪淘宝网:cxcad.taobao.com
;联系QQ:775452144
;编译时间:" + DateTime.Now.ToString();
            s += "\r\n(PRV-DEF (:target . \"" + _vlxName + ".VLX\")";
            if (_bActicex)
            {
                s += "(:active-x . T)";
            }
            else
            {
                s += "(:active-x)";
            }
            if (_bNameSpaceIsSeparate)
            {
                s += "\r\n	 (:separate-namespace . T)";
            }
            else
            {
                s += "\r\n	 (:separate-namespace)";
            }
            s += @"
	 (:protected . T)
	 (:load-file-list";
            foreach (var x in FileS)
            {
                if (Path.GetExtension(x.Key) == ".lsp")
                {
                    s += "\r\n	   (:lsp \"" + x.Key.Replace("\\", "/") + "\")";
                }
            }
            s += "\r\n	 )";
            s += "\r\n	 (:require-file-list";
            foreach (var x in FileS)
            {
                if (Path.GetExtension(x.Key) != ".lsp")
                {
                    s += "\r\n	   (:" + Path.GetExtension(x.Key).Substring(1) + " \"" + x.Key.Replace("\\", "/") + "\")";
                }
            }
            s += "\r\n         )";
            s += @"
	 (:ob-directory)
	 (:tmp-directory)
	 (:optimization . st)
)";
            Directory.CreateDirectory(Path.GetDirectoryName(_prvPath));
            File.WriteAllText(_prvPath, s, Encoding.Default);
            Fsxm.LispEdit.Project.CombPrvToVlx(_prvPath);
        }


    }
    /// <summary>   
    /// 支持XML序列化的泛型 Dictionary   
    /// </summary>   
    /// <typeparam name="TKey"></typeparam>   
    /// <typeparam name="TValue"></typeparam>   
    [XmlRoot("SerializableDictionary")]
    public class SerializableDictionary<TKey, TValue>
        : Dictionary<TKey, TValue>, IXmlSerializable
    {

        #region 构造函数
        public SerializableDictionary()
            : base()
        {
        }
        public SerializableDictionary(IDictionary<TKey, TValue> dictionary)
            : base(dictionary)
        {
        }

        public SerializableDictionary(IEqualityComparer<TKey> comparer)
            : base(comparer)
        {
        }

        public SerializableDictionary(int capacity)
            : base(capacity)
        {
        }
        public SerializableDictionary(int capacity, IEqualityComparer<TKey> comparer)
            : base(capacity, comparer)
        {
        }
        protected SerializableDictionary(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }
        #endregion
        #region IXmlSerializable Members
        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }
        /// <summary>   
        /// 从对象的 XML 表示形式生成该对象   
        /// </summary>   
        /// <param name="reader"></param>   
        public void ReadXml(System.Xml.XmlReader reader)
        {
            XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
            XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
            bool wasEmpty = reader.IsEmptyElement;
            reader.Read();
            if (wasEmpty)
                return;
            while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
            {
                reader.ReadStartElement("item");
                reader.ReadStartElement("key");
                TKey key = (TKey)keySerializer.Deserialize(reader);
                reader.ReadEndElement();
                reader.ReadStartElement("value");
                TValue value = (TValue)valueSerializer.Deserialize(reader);
                reader.ReadEndElement();
                this.Add(key, value);
                reader.ReadEndElement();
                reader.MoveToContent();
            }
            reader.ReadEndElement();
        }

        /**/
        /// <summary>   
        /// 将对象转换为其 XML 表示形式   
        /// </summary>   
        /// <param name="writer"></param>   
        public void WriteXml(System.Xml.XmlWriter writer)
        {
            XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
            XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
            foreach (TKey key in this.Keys)
            {
                writer.WriteStartElement("item");
                writer.WriteStartElement("key");
                keySerializer.Serialize(writer, key);
                writer.WriteEndElement();
                writer.WriteStartElement("value");
                TValue value = this[key];
                valueSerializer.Serialize(writer, value);
                writer.WriteEndElement();
                writer.WriteEndElement();
            }
        }
        #endregion
    }
}